import React, { PropsWithChildren } from 'react';
import { Form, message, Spin } from 'antd';
import {
  ModalForm,
  ProFormDigit,
  ProFormList,
  ProFormSelect,
  ProFormText,
  ProFormTextArea
} from '@ant-design/pro-components';
import { useRequest } from 'ahooks';
import {
  evaluationV1AdminControllerCreateEvaluationArticle,
  evaluationV1AdminControllerShowEvaluation,
  evaluationV1AdminControllerUpdateEvaluationArticle,
} from "@/services/auto/evaluationAdmin";
import FileUpload from "@/components/FileUpload";
import { evaluationCategory, BooleanNumber, FileGroup, SpecificationValueType } from "common/utils/data";
import { brandV1AdminControllerIndex } from "@/services/auto/brandAdmin";
import Keywords from 'common/component/Keywords';
import DataTables from './DataTables';
import {DndContext} from '@dnd-kit/core';
import { SortableContext, arrayMove } from "@dnd-kit/sortable";
import SpecificationItem from "./SpecificationItem";
import ImpulseResponseFileItem from "./ImpulseResponseFileItem";
import { DEFAULT_DATA_GROUP } from "@/utils";

interface FormData extends Omit<API.EvaluationAdminCreateDto, 'datas' | 'specifications' | 'impulseResponseFiles'> {
  datas: (API.EvaluationAdminCreateDataItem & {
    key: number;
  })[]
  specifications?: (Omit<API.EvaluationAdminCreateSpecificationItem, 'value'> & {
    uuid: string;
    value: any;
  })[]
  dataGroups?: string[];
  impulseResponseFiles?: (Omit<API.EvaluationAdminCreateFileItem, 'url'> & {uuid: string;urls?:string[]})[];
}

interface Props {
  data?: API.EvaluationAdminIndexResult;
  reload?: () => void;
  presetSpecifications: API.SpecificationAllResult[];
}

export default function Add(props: PropsWithChildren<Props>){
  const { data, reload, presetSpecifications, children } = props;

  const [form] = Form.useForm<FormData>();

  const dataGroups = Form.useWatch('dataGroups',form);

  const {
    runAsync: getArticlesDetailRun,
    loading: getArticlesDetailLoading,
  } = useRequest(()=>evaluationV1AdminControllerShowEvaluation({uuid: data!.uuid}, {timeout: 300000}), {
    manual: true,
    onSuccess: data => {
      const formData: FormData = {
        title: data.title,
        keywords: data.article.keywords,
        brandUuid: data.brandUuid,
        price: data.price,
        buyUrl: data.buyUrl,
        category: data.category,
        thumbnails: data.article.thumbnails,
        desc: data.article.desc,
        datas: data.datas?.map((item) => {
          return {
            ...item,
            key: Math.random(),
          };
        }),
        specifications: data.specifications?.map(item=>{
          const specification = presetSpecifications.find(it=>it.uuid === item.specificationUuid)!;
          return {
            ...item,
            value: ({
              [SpecificationValueType.TEXT]: (val: string)=>val,
              [SpecificationValueType.NUMBER]: (val: string)=>Number(val),
              [SpecificationValueType.SELECT]: (val: string)=>{
                const res = val.replace(/^;/, '').replace(/;$/, '');
                if(specification.extra.multiple){
                  return res.split(';');
                }
                return res;
              },
            }[specification.valueType])(item.value)
          }
        }),
        impulseResponseFiles: data.impulseResponseFiles?.map(item=>{
          const {url, ...restItem} = item;
          return {
            ...restItem,
            urls: url ? [url] : undefined,
          }
        }),
      };

      const dataGroups = Array.from(new Set(data.datas.filter(item=>!!item.group).map(item=>item.group)));
      if(dataGroups.length){
        formData.dataGroups = dataGroups;
      }

      form.setFieldsValue(formData);
    }
  });

  const {
    data: getBrandsData,
    runAsync: getBrandsRun,
    loading: getBrandsLoading
  } = useRequest(()=>brandV1AdminControllerIndex({pageSize: 99999, enableTitleSort: BooleanNumber.true}), {
    manual: true,
  });
  const category = Form.useWatch('category',form);

  const specifications = Form.useWatch('specifications',form);

  const impulseResponseFiles = Form.useWatch('impulseResponseFiles',form);

  return (
    <ModalForm
      layout="horizontal"
      width={1200}
      labelCol={{style: {width: 100}}}
      modalProps={{
        maskClosable: false,
      }}
      form={form}
      onOpenChange={(val) => {
        if (val) {
          getBrandsRun();
          if (data?.uuid) {
            getArticlesDetailRun();
          }
        } else {
          form.resetFields();
        }
      }}
      title={data?.uuid ? '编辑评测数据' : '添加评测数据'}
      trigger={children as JSX.Element}
      onFinish={(values) => {
        console.log(values);
        const {dataGroups, ...restValues} = values;
        let service;
        const newValues: API.EvaluationAdminCreateDto = {
          ...restValues,
          datas: restValues.datas.map(item=>{
            return {
              ...item,
              defaultShow: item.defaultShow ? BooleanNumber.true : BooleanNumber.false,
            }
          }),
          specifications: restValues.specifications?.map(item=>{
            const {uuid, ...restItem} = item;
            const specification = presetSpecifications.find(it=>it.uuid === item.specificationUuid)!;
            return {
              ...restItem,
              value: ({
                [SpecificationValueType.TEXT]: (val: string)=>val,
                [SpecificationValueType.NUMBER]: (val: number)=>val.toString(),
                [SpecificationValueType.SELECT]: (val: string | string[])=>{
                  let res: string;
                  if(specification.extra.multiple){
                    res = (val as string[]).join(';');
                  }else{
                    res = val as string;
                  }

                  return `;${res};`
                },
                // @ts-ignore
              }[specification.valueType])(item.value),
            }
          }),
          impulseResponseFiles: restValues.impulseResponseFiles?.map(item=>{
            const {uuid, ...restItem} = item;
            return {
              ...restItem,
              url: restItem.urls?.[0],
            };
          })
        };
        if (data?.uuid) {
          service = evaluationV1AdminControllerUpdateEvaluationArticle({uuid: data.uuid},newValues, {timeout: 300000});
        } else {
          service = evaluationV1AdminControllerCreateEvaluationArticle(newValues, {timeout: 300000});
        }
        return service
          .then(() => {
            message.success('操作成功');
            reload?.();
            return true;
          })
          .catch(() => {
            return false;
          });
      }}
    >
      <Spin spinning={getArticlesDetailLoading}>
        <ProFormText
          name="title"
          label="标题"
          rules={[{ required: true, message: '请输入' }]}
          fieldProps={{
            maxLength: 50,
          }}
        />
        <Form.Item
          name="thumbnails"
          label="封面图"
        >
          <FileUpload max={1} fileGroup={FileGroup.ARTICLE} />
        </Form.Item>
        <ProFormSelect
          label="分类"
          name="category"
          options={evaluationCategory.$listSelect}
          rules={[{ required: true, message: '请选择' }]}
        />
        <ProFormSelect
          name="brandUuid"
          label="品牌"
          rules={[{ required: true, message: '请选择' }]}
          options={getBrandsData?.list.map(item=>{
            return {
              label: item.title,
              value: item.uuid,
            }
          })}
          fieldProps={{
            loading: getBrandsLoading,
            optionFilterProp: 'label',
            showSearch: true,
          }}
        />
        <Form.Item name="keywords" label="关键词">
          <Keywords />
        </Form.Item>
        <ProFormDigit
          name="price"
          label="价格"
          fieldProps={{
            precision: 2,
            max: 9999999999.99,
            min: 0,
          }}
        />
        <ProFormText
          name="buyUrl"
          label="购买链接"
          rules={[{ message: '请填写标准的url格式', type: 'url' }]}
          fieldProps={{
            maxLength: 500,
          }}
        />
        <ProFormTextArea
          name="desc"
          label="描述"
          fieldProps={{
            maxLength: 500,
          }}
        />
        <DndContext onDragEnd={(e)=>{
          const { active,over } = e
          const activeIndex = specifications!.findIndex(item=>item.uuid === active.id);
          const overIndex = specifications!.findIndex(item=>item.uuid === over!.id);
          form.setFieldsValue({
            specifications: arrayMove(specifications!,activeIndex,overIndex)
          })
        }}>
          <SortableContext
            items={specifications?.map(item=>item.uuid) ?? []}
          >
        <ProFormList
          copyIconProps={false}
          label="规格"
          name="specifications"
          creatorButtonProps={{
            position: 'bottom',
            creatorButtonText: '新增一种规格',
          }}
          creatorRecord={()=>{
            return {
              uuid: `key-${Math.random().toString()}`,
            }
          }}
          rules={[
            {
              validator: (_, val: FormData['specifications']) => {
                if(!val){
                  return Promise.resolve();
                }
                for (let i = 0; i < val.length; i++) {
                  const res = val.filter(item=>item.specificationUuid ===val[i].specificationUuid);
                  if (res.length > 1) {
                    return Promise.reject(
                      new Error(`第${i + 1}项规格项有重复`),
                    );
                  }
                }
                return Promise.resolve();
              },
            },
          ]}
        >
          {(f, index, action)=>{
            const uuid = form.getFieldValue(['specifications', index, 'uuid']);

            return <SpecificationItem
              presetSpecifications={presetSpecifications.filter(item=>item.category === category)}
              key={uuid}
              uuid={uuid}
            />
          }}
        </ProFormList>
          </SortableContext>
        </DndContext>
        <Form.Item name="dataGroups" label="预设数据分组" initialValue={[DEFAULT_DATA_GROUP]}>
          <Keywords min={1} beforeDelete={(value)=>{
            if(form.getFieldsValue().datas.some(item=>item.group === value)){
              message.warning('有数据在使用该分组，请去掉关联后再删除');
              return false
            }
            return true;
          }} />
        </Form.Item>
        <Form.Item
          name="datas"
          label="数据"
          validateTrigger="onFinish"
          rules={[
            {
              required: true,
              validator: (_, val: FormData['datas']) => {
                if (!val?.length) {
                  return Promise.reject(new Error('至少有一个测试项'));
                }
                for (let i = 0; i < val.length; i++) {
                  if (!val[i].projectUuid || (!val[i].data && !val[i].img && !val[i].json)) {
                    return Promise.reject(
                      new Error(`第${i + 1}项测试项未填写完毕`),
                    );
                  }
                  const nameRes = val.filter(item=>item.name ===val[i].name && item.projectUuid === val[i].projectUuid);
                  if (nameRes.length > 1) {
                    return Promise.reject(
                      new Error(`第${i + 1}项测试项的名称有重复`),
                    );
                  }
                  if(val[i].group){
                    const groupRes = val.filter(item=>item.group ===val[i].group && item.projectUuid === val[i].projectUuid);
                    if (groupRes.length > 1) {
                      return Promise.reject(
                        new Error(`第${i + 1}项测试项的分组有重复`),
                      );
                    }
                  }

                }
                return Promise.resolve();
              },
            },
          ]}
        >
          <DataTables dataGroups={dataGroups} />
        </Form.Item>
        <DndContext onDragEnd={(e)=>{
          const { active,over } = e
          const activeIndex = impulseResponseFiles!.findIndex(item=>item.uuid === active.id);
          const overIndex = impulseResponseFiles!.findIndex(item=>item.uuid === over!.id);
          form.setFieldsValue({
            impulseResponseFiles: arrayMove(impulseResponseFiles!,activeIndex,overIndex)
          })
        }}>
          <SortableContext
            items={impulseResponseFiles?.map(item=>item.uuid) ?? []}
          >
            <ProFormList
              copyIconProps={false}
              label="冲激响应文件"
              name="impulseResponseFiles"
              creatorButtonProps={{
                position: 'bottom',
                creatorButtonText: '新增一种冲激响应文件',
              }}
              creatorRecord={()=>{
                return {
                  uuid: `key-${Math.random().toString()}`,
                  group: DEFAULT_DATA_GROUP,
                }
              }}
              rules={[
                {
                  validator: (_, val: FormData['impulseResponseFiles']) => {
                    if(!val){
                      return Promise.resolve();
                    }
                    for (let i = 0; i < val.length; i++) {
                      const res = val.filter(item=>item.group ===val[i].group);
                      if (res.length > 1) {
                        return Promise.reject(
                          new Error(`第${i + 1}项分组有重复`),
                        );
                      }
                    }
                    return Promise.resolve();
                  },
                },
              ]}
            >
              {(f, index, action)=>{
                const uuid = form.getFieldValue(['impulseResponseFiles', index, 'uuid']);

                return <ImpulseResponseFileItem
                  dataGroups={dataGroups}
                  key={uuid}
                  uuid={uuid}
                />
              }}
            </ProFormList>
          </SortableContext>
        </DndContext>
      </Spin>
    </ModalForm>
  );
};
